package mosdi.subcommands;

import java.util.List;

import mosdi.fa.FiniteMemoryTextModel;
import mosdi.fa.IIDTextModel;
import mosdi.fa.MarkovianTextModel;
import mosdi.util.Alphabet;
import mosdi.util.CodonAlphabet;
import mosdi.util.Log;
import mosdi.util.NamedSequence;
import mosdi.util.SequenceUtils;

public class PrintCodonModelSubcommand extends Subcommand {
	
	@Override
	public String usage() {
		return
		super.usage()+" [options] <exons.fasta>\n" +
		"\n" +
		"  <exons.fasta> a file containing coding regions in FASTA format.\n" +
		"\n" +
		"Options:\n" +
		"  -O <order>: Order of background model to be estimated from input text (default: 1)\n" +
		"  -p <pseudocounts>: Pseudocounts for estimation of text model (default: 0.1)";
	}

	@Override
	public String description() {
		return "Prints transition probabilities of a codon model estimated from given coding regions.";
	}

	@Override
	public String name() {
		return "print-codon-model";
	}

	private String codonToString(int codon) {
		return Alphabet.getDnaAlphabet().buildString(CodonAlphabet.get(codon));
	}
	
	private String codonsToString(int[] codons) {
		StringBuffer sb = new StringBuffer();
		for (int i=0; i<codons.length; ++i) {
			if (i>0) sb.append('|');
			sb.append(codonToString(codons[i]));
		}
		return sb.toString();
	}
	
	@Override
	public int run(String[] args) {
		parseOptions(args, 1, "O:p:");

		// Option dependencies
		// -- none --

		// Mandatory arguments
		String exonFilename = getStringArgument(0);

		// Options
		int modelOrder = getNonNegativeIntOption("O", 1);
		double pseudoCounts = this.getRangedDoubleOption("p", 0.0, Double.POSITIVE_INFINITY, 0.1);
		
		Alphabet dnaAlphabet = Alphabet.getDnaAlphabet();
		Log.printf(Log.Level.VERBOSE, "Reading file %s\n", exonFilename);
		List<NamedSequence> namedSequences = null;
		try {
			namedSequences = SequenceUtils.readFastaFile(exonFilename, dnaAlphabet, true);
		} catch (Exception e) {
			Log.errorln(e.getMessage());
			return 1;
		}
		Log.printf(Log.Level.VERBOSE, "Read %,d sequences\n", namedSequences.size());
		FiniteMemoryTextModel codonModel =  SequenceUtils.buildCodonModelFromNamedSequences(namedSequences, modelOrder, pseudoCounts);
		
		if (codonModel instanceof IIDTextModel) {
			IIDTextModel model =  (IIDTextModel)codonModel;
			for (int codon=0; codon<CodonAlphabet.size(); ++codon) {
				Log.printf(Log.Level.STANDARD, "%s %f\n", codonToString(codon), model.getProbability(0, codon));
			}
		} else {
			MarkovianTextModel model =  (MarkovianTextModel)codonModel;
			for (int state=0; state<model.getStateCount(); ++state) {
				for (int codon=0; codon<CodonAlphabet.size(); ++codon) {
					Log.printf(Log.Level.STANDARD, "%s-->%s: %f\n", codonsToString(model.getContext(state)), codonToString(codon), model.getProbability(state, codon));
				}
			}
		}
		
		return 0;
	}
}
